package com.gtlab1207.br_awareness.services;

import com.gtlab1207.br_awareness.models.dao.TotalEventDao;
import com.gtlab1207.br_awareness.models.domain.LogRecord;
import com.gtlab1207.br_awareness.models.domain.SecurityEvent;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class TotalEventService {

    @Autowired
    private TotalEventDao totalEventDao;
    @Autowired
    private LogRecordService logRecordService;

    @Transactional
    public List<SecurityEvent> selectEventInSevenDay(){
        // 汇总最近七天的事件
//        List<LogRecord> logRecords = logRecordService.showAllLogs();
        List<LogRecord> logRecords = logRecordService.selectEventInSevenDay();
        if (!logRecords.isEmpty()) {
            //删除以往的记录
            totalEventDao.deleteEventByState(0);
            // 修改之前的汇总的事件记录的状态
            updateEventState(1,0);
            Map<String, List<LogRecord>> collect = logRecords.stream().collect(
                    Collectors.groupingBy(LogRecord::getDip)
            );
            final List<SecurityEvent> securityEvents = new ArrayList<>();

            collect.forEach((dip,value)->{
//            System.out.println("====="+key+"---"+value);
                SecurityEvent securityEvent = new SecurityEvent();
                securityEvent.setIp(dip);
                Object[] eventMessages =  value.stream().map(
                        item -> {
                            return item.getEvent();
                        }
                ).collect(Collectors.toList()).toArray();

                securityEvent.setSecurityEvent(StringUtils.arrayToDelimitedString(eventMessages ,"||"));
                securityEvent.setState(1);
                securityEvent.setScore(100.0-value.size()*5.0);
                securityEvent.setCreateBy("test");
                securityEvents.add(securityEvent);
            });

            //3 回写到汇总的事件表中
            securityEvents.forEach((securityEvent)->{
                addSecurityEvent(securityEvent);
            });
        }

        //4 返回分数和最近七天事件记录
        return selectListByState(1);
    }

    @Transactional
    public Map<String,Map<String,Double> > selectEventScoreEveryDay(){
        // 汇总最近七天的事件
//        List<LogRecord> logRecords = logRecordService.showAllLogs();
        List<LogRecord> logRecords = logRecordService.selectEventInSevenDay();
        if (!logRecords.isEmpty()) {
            selectEventInSevenDay();

            Map<String, List<LogRecord>> collect = logRecords.stream().collect(
                    Collectors.groupingBy(LogRecord::getDip)
            );
            //第一个String是ip 第二个String是时间字符串 第三个Double是分数
            final Map<String,Map<String,Double> > eventScore = new HashMap<>();
            //将根据ip分类的集合再根据时间分类
            collect.forEach((dip,eventsByIp)->{
                Map<String, List<LogRecord>> eventsByTime = eventsByIp.stream().collect(
                        Collectors.groupingBy(item -> {
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//                            System.out.println("====" + sdf.format(item.getTime()));
                            return sdf.format(item.getTime());
                        }));
                Map<String,Double> eventScoreByDay= new HashMap<>();
                //遍历先根据ip和后根据时间分类的集合
                eventsByTime.forEach((day,events)->{
                    int eventSize = 0;
                    eventSize = eventSize +events.size();
                    //某个ip,从一天到第七天的事件记录
                    eventScoreByDay.put(day,(100.0-eventSize*5.0));
                });
                eventScore.put(dip,eventScoreByDay);
            });
            //4 返回分数和最近七天事件记录
            System.out.println("======"+eventScore);
            return eventScore;
        }else {
            return null;
        }
    }

    private void updateEventState(Integer oldState,Integer newState) {
        List<SecurityEvent> events = totalEventDao.selectListByState(oldState);
        events.stream().map(
                event -> {
                    event.setSecurityEvent(null);
                    event.setScore(null);
                    event.setState(newState);
                    return event;
                }
        ).forEach(newSecurityEvent->{
            updateSecurityEvent(newSecurityEvent);
        });
    }

    @Transactional
    public void updateAllIpScore(){
        List<SecurityEvent> securityEvents = selectListByState(1);
        System.out.println("======"+securityEvents.size());
        securityEvents.stream().map(
                securityEvent -> {
                    securityEvent.setSecurityEvent(null);
                    securityEvent.setState(null);
                    securityEvent.setScore(100.0);
                    return securityEvent;
                }
        ).forEach(newSecurityEvent->{
            System.out.println("======"+newSecurityEvent);
            updateSecurityEvent(newSecurityEvent);
        });
    }
    @Transactional
    public int addSecurityEvent(SecurityEvent record) {
        return totalEventDao.addSecurityEvent(record);
    }
    @Transactional
    public int deleteSecurityEvent(String ip) {
        return totalEventDao.deleteSecurityEventByIp(ip);

    }
    @Transactional
    public int deleteAll() {
        return totalEventDao.deleteAll();
    }
    @Transactional
    public int updateSecurityEvent(SecurityEvent record) {
        return totalEventDao.updateSecurityEventByIp(record);

    }
    public List<SecurityEvent> selectListByState(Integer state) {
        return totalEventDao.selectListByState(state);

    }
    public List<SecurityEvent> selectAll() {
        return totalEventDao.selectAll();

    }

    public List<SecurityEvent> selectSecurityEventByCondition(SecurityEvent condition) {
        return totalEventDao.selectSecurityEventByCondition(condition);
    }

    public SecurityEvent selectSecurityEventByIp(String ip) {
        return totalEventDao.selectSecurityEventByIp(ip);
    }


}
